package com.xyy.saas.payment.service.job.impl;

import com.xyy.saas.payment.adapter.RouteManager;
import com.xyy.saas.payment.callback.CallbackRunner;
import com.xyy.saas.payment.common.constants.BaseConstants;
import com.xyy.saas.payment.common.constants.ChannelConstants;
import com.xyy.saas.payment.common.constants.ChannelProductConstants;
import com.xyy.saas.payment.constants.Constants;
import com.xyy.saas.payment.cores.bo.OpenPayBo;
import com.xyy.saas.payment.cores.bo.QueryCreateAllPayBo;
import com.xyy.saas.payment.cores.enums.FBankPowerIdEnum;
import com.xyy.saas.payment.cores.enums.OpenAccountApplyStatusEnum;
import com.xyy.saas.payment.cores.enums.OpenAccountAuthorizeStatusEnum;
import com.xyy.saas.payment.cores.enums.OpenPayStatusEnum;
import com.xyy.saas.payment.cores.vo.CallbackResultVo;
import com.xyy.saas.payment.dao.model.*;
import com.xyy.saas.payment.exception.PaymentException;
import com.xyy.saas.payment.manage.cores.enums.ResultCodeEnum;
import com.xyy.saas.payment.manage.cores.vo.ResultVO;
import com.xyy.saas.payment.service.*;
import com.xyy.saas.payment.service.job.QueryOpenAccountJobService;
import com.xyy.saas.payment.util.DateUtil;
import com.xyy.saas.payment.util.JSONUtils;
import com.xyy.saas.payment.util.WxUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class QueryOpenAccountJobServiceImpl implements QueryOpenAccountJobService {

    @Autowired
    private CallbackRunner callbackRunner;
    @Autowired
    private PayAccountService payAccountService;
    @Resource
    private ApplyOpenAccountStatusService applyOpenAccountStatusService;
    @Resource
    private ApplypayUserInfoService applypayUserInfoService;
    @Resource
    private OpenAccountService openAccountService;
    @Resource
    private OpenpayInfoService openpayInfoService;
    @Resource
    private ThirdUserInfoService thirdUserInfoService;
    @Resource
    private RouteManager routeManager;

    @Value("${wx.open_account.queryStatusUrl}")
    private String wxQueryStatusUrl;
    @Value("${wx.open_account.applymentUrl}")
    private String wxApplymentUrl;
    @Value("${wx.open_account.merchantId}")
    private String merchantId;
    @Value("${wx.open_account.certSerial}")
    private String certSerial;
    @Value("${wx.open_account.apiV3Key}")
    private String apiV3Key;
    @Value("${wx.open_account.merchantPrivateKey}")
    private String merchantPrivateKey;

    @Override
    public void monitorOpenAccountApplyStatus() {
        // 查询
        log.info("QueryOpenAccountStatusService#monitorOpenAccountApplyStatus begin monitor.");
        Long beginTime = System.currentTimeMillis();
        Integer cnt = 0;
        Integer offset = 0;
        while (true) {
            // 查询如下状态：审核中、编辑中、待确认联系信息、待账户验证、审核驳回、已冻结
            List<Integer> statusList = Arrays.asList(OpenAccountApplyStatusEnum.APPLYMENT_STATE_WAITTING_FOR_AUDIT.getStatus()
                                                    , OpenAccountApplyStatusEnum.APPLYMENT_STATE_EDITTING.getStatus()
                                                    , OpenAccountApplyStatusEnum.APPLYMENT_STATE_WAITTING_FOR_CONFIRM_CONTACT.getStatus()
                                                    , OpenAccountApplyStatusEnum.APPLYMENT_STATE_WAITTING_FOR_CONFIRM_LEGALPERSON.getStatus()
                                                    , OpenAccountApplyStatusEnum.APPLYMENT_STATE_REJECTED.getStatus()
                                                    , OpenAccountApplyStatusEnum.APPLYMENT_STATE_FREEZED.getStatus());
            List<ApplyOpenAccountStatus> applyOpenAccountStatuseList = applyOpenAccountStatusService.queryByStatusPage(statusList,offset, Constants.DEFAULT_PAGE_SIZE);

            if (CollectionUtils.isEmpty(applyOpenAccountStatuseList)) {
                break;
            }

            cnt += applyOpenAccountStatuseList.size();
            offset += Constants.DEFAULT_PAGE_SIZE;

            for (ApplyOpenAccountStatus applyOpenAccountStatus : applyOpenAccountStatuseList) {
                // 判断是否超过三十天二维码是否失效 处理 待确认联系信息 待账户验证 状态的
                if(OpenAccountApplyStatusEnum.APPLYMENT_STATE_WAITTING_FOR_CONFIRM_CONTACT.getStatus() == applyOpenAccountStatus.getStatus()
                    || OpenAccountApplyStatusEnum.APPLYMENT_STATE_WAITTING_FOR_CONFIRM_LEGALPERSON.getStatus() == applyOpenAccountStatus.getStatus()){
                    // 计算超过三十天的重新申请
                    Calendar calendar = Calendar.getInstance();
                    calendar.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH)-30);
                    if(calendar.getTime().after(applyOpenAccountStatus.getCreateTime())) {
                        // 撤销后重新申请
                        ResultVO resultVO = openAccountService.againOpenAccountApplyment(applyOpenAccountStatus.getApplyCode());
                        if(!resultVO.isSuccess()) {
                            log.error("QueryOpenAccountStatusService#monitorOpenAccountApplyStatus againOpenAccountApplyment fail. resultVO:{}", JSONUtils.toJSON(resultVO));
                        }
                        continue;
                    }
                }
                // 其余状态需查询
                String applymentId = applyOpenAccountStatus.getApplymentId();
                String businessCode = applyOpenAccountStatus.getApplyCode();
                // 优先 使用applymentId查询
                if(StringUtils.isNotBlank(applymentId)) {
                    // 发送请求
                    Map<String, String> respMap = null;
                    respMap = queryOpenAccountStatusFromWx(wxApplymentUrl + "?applyment_id=" + applymentId);
                    if(null == respMap) {
                        continue;
                    }
                    // 同步本地数据
                    boolean isSync = syncStatusData(applyOpenAccountStatus, respMap);
                    // 响应业务侧,只有状态变更 数据库数据同步后才回调业务
                    if(isSync) {
                        notification(applyOpenAccountStatus, respMap);
                    }
                    continue;
                }

                log.warn("QueryOpenAccountStatusService#monitorOpenAccountApplyStatus applymentId is blank. applyOpenAccountStatus:{}", JSONUtils.toJSON(applyOpenAccountStatus));
                if(StringUtils.isNotBlank(businessCode)) {
                    // 发送请求 TODO 改造
                    Map<String, String> respMap = null;
                    respMap = queryOpenAccountStatusFromWx(wxApplymentUrl + "?business_code=" + businessCode);
                    if(null == respMap) {
                        continue;
                    }
                    // 同步本地数据
                    boolean isSync = syncStatusData(applyOpenAccountStatus, respMap);
                    // 响应业务侧,只有状态变更 数据库数据同步后才回调业务
                    if(isSync) {
                        notification(applyOpenAccountStatus, respMap);
                    }
                    continue;
                }
                log.error("QueryOpenAccountStatusService#monitorOpenAccountApplyStatus applymentId and applyCode is blank. applyOpenAccountStatus:{}", JSONUtils.toJSON(applyOpenAccountStatus));
            }
        }
        Long endTime = System.currentTimeMillis();
        log.info("QueryOpenAccountStatusService#monitorOpenAccountApplyStatus end monitor. size:{} time:{}ms", cnt, beginTime-endTime);
    }

    @Override
    public void monitorOpenAccountAuthorizeStatus() {
        // 查询
        log.info("QueryOpenAccountAuthorizeStatus#monitorOpenAccountAuthorizeStatus begin monitor.");
        Long beginTime = System.currentTimeMillis();
        Integer cnt = 0;
        Integer offset = 0;
        while (true) {
            // 查询如下状态：待确认联系信息、待账户验证、审核通过、已冻结
            List<Integer> statusList = Arrays.asList(OpenAccountApplyStatusEnum.APPLYMENT_STATE_PASSED.getStatus(),OpenAccountApplyStatusEnum.APPLYMENT_STATE_FREEZED.getStatus());
            List<ApplyOpenAccountStatus> applyOpenAccountStatuseList = applyOpenAccountStatusService.queryByStatusPage(statusList,offset, Constants.DEFAULT_PAGE_SIZE);

            if (org.springframework.util.CollectionUtils.isEmpty(applyOpenAccountStatuseList)) {
                break;
            }

            cnt += applyOpenAccountStatuseList.size();
            offset += Constants.DEFAULT_PAGE_SIZE;

            for (ApplyOpenAccountStatus applyOpenAccountStatus : applyOpenAccountStatuseList) {

                // 已授权的无需处理 或者 没有审核通过的无需处理
                if(applyOpenAccountStatus.getAuthorize() == OpenAccountAuthorizeStatusEnum.AUTHORIZE_STATE_AUTHORIZED.getStatus()) {
                    continue;
                }
                String accountId = applyOpenAccountStatus.getAccountId();
                PayAccount payAccount = payAccountService.getPayAccountByAccountId(accountId);
                // 其余的需要查询授权状态
                ApplypayUserInfo applypayUserInfo = applypayUserInfoService.queryUserInfoByAccountId(accountId);
                if(null == applypayUserInfo || org.springframework.util.StringUtils.isEmpty(applypayUserInfo.getSubMchid())) {
                    log.error("QueryOpenAccountAuthorizeStatus#monitorOpenAccountAuthorizeStatus query applypayUserInfo is exist or sub_mchid is empty. accountId:{}", accountId);
                    continue;
                }
                String realUrl = wxQueryStatusUrl.replace("{sub_mchid}", applypayUserInfo.getSubMchid());

                try {
                    String response = "";
                    WxUtil.WxCertEntity wxCert = WxUtil.buildWxCert(merchantId, apiV3Key, certSerial, merchantPrivateKey);

                    Map<String, String> header = new HashMap<>();
                    header.put("Accept","application/json");
                    header.put("Content-type", "application/json; charset=utf-8");
                    header.put("Wechatpay-Serial", certSerial);
                    response = wxCert.wxHttpGetRequest(realUrl, header);
                    log.info("QueryOpenAccountAuthorizeStatus#queryOpenAccountStatusFromWx query param. reqUrl:{}, response:{}", realUrl, response);
                    if(org.springframework.util.StringUtils.isEmpty(response)) {
                        log.error("QueryOpenAccountAuthorizeStatus#queryOpenAccountStatusFromWx query fail. response:{}", response);
                        continue;
                    }
                    Map<String, String> respMap = JSONUtils.parse2Map(response, String.class, String.class);
                    String authorizeState = respMap.get("authorize_state");
                    // 如果已授权，则更新数据，并通知业务
                    if(OpenAccountAuthorizeStatusEnum.valueOf(authorizeState).getStatus() == OpenAccountAuthorizeStatusEnum.AUTHORIZE_STATE_AUTHORIZED.getStatus()) {
                        // 保存数据库
                        ApplyOpenAccountStatus updObj = new ApplyOpenAccountStatus();
                        updObj.setId(applyOpenAccountStatus.getId());
                        updObj.setAuthorize(OpenAccountAuthorizeStatusEnum.AUTHORIZE_STATE_AUTHORIZED.getStatus());
                        updObj.setUpdateTime(new Date());
                        int rows = applyOpenAccountStatusService.updateByPrimaryKeySelective(updObj);
                        if(rows < 1) {
                            log.error("QueryOpenAccountAuthorizeStatus#monitorOpenAccountAuthorizeStatus update Authorize status fail. updObj:{}, applyOpenAccountStatus:{}", JSONUtils.toJSON(updObj), JSONUtils.toJSON(applyOpenAccountStatus));
                        }

                        // check 富民 渠道支付功能是否配置完成
                        boolean isNotify = true;
                        List<OpenpayInfo> openpayInfos = openpayInfoService.queryUserInfoByAccountId(accountId, applypayUserInfo.getThirdUserInfoId());
                        for (OpenpayInfo openpayInfo : openpayInfos) {
                            if(FBankPowerIdEnum.WX_MINI.getPowerId().equals(openpayInfo.getPowerId())
                                || FBankPowerIdEnum.WX_OFFICIAL.getPowerId().equals(openpayInfo.getPowerId())) {
                                if(!OpenPayStatusEnum.SUCCESS_PAY_CHANNEL.getStatus().equals(openpayInfo.getStatus())) {
                                    isNotify = false;
                                }
                            }
                        }

                        // 通知业务
                        if(isNotify) {
                            callbackRunner.callback(payAccount.getBusinessUserId(), CallbackResultVo.TYPE_OPEN_ACCOUNT_SUCCESS, 0, 0, null, applypayUserInfo.getCallback(), "");
                        }
                    }
                } catch (Exception e) {
                    log.error("QueryOpenAccountAuthorizeStatus#monitorOpenAccountAuthorizeStatus query authorize status fail. e:{}", e);
                }
            }
        }
        Long endTime = System.currentTimeMillis();
        log.info("QueryOpenAccountAuthorizeStatus#monitorOpenAccountAuthorizeStatus end monitor. size:{} time:{}ms", cnt, beginTime-endTime);
    }

    /**
     * 查询微信状态
     */
    private Map<String, String> queryOpenAccountStatusFromWx(String reqUrl){
        try {
            log.info("QueryOpenAccountStatusService#queryOpenAccountStatusFromWx start request open account status. reqUrl:{}", reqUrl);
            WxUtil.WxCertEntity wxCert = WxUtil.buildWxCert(merchantId, apiV3Key, certSerial, merchantPrivateKey);

            Map<String, String> header = new HashMap<>();
            header.put("Accept","application/json");
            header.put("Content-type", "application/json; charset=utf-8");
            header.put("Wechatpay-Serial", certSerial);
            String response = wxCert.wxHttpGetRequest(reqUrl, header);
            log.info("QueryOpenAccountStatusService#queryOpenAccountStatusFromWx end request open account status. reqUrl:{} response:{}", reqUrl, response);

            return JSONUtils.parse2Map(response, String.class, String.class);
        } catch (Exception e) {
            log.error("QueryOpenAccountStatusService#queryOpenAccountStatusFromWx request open account status exception. e:{}", e);
        }
        return null;
    }
    /**
     * 同步数据
     */
    private boolean syncStatusData(ApplyOpenAccountStatus source, Map<String, String> target) {
        String applymentState = target.get("applyment_state");
        OpenAccountApplyStatusEnum retEnum = OpenAccountApplyStatusEnum.valueOf(applymentState);

        // 同步库状态
        try {
            if(source.getStatus() != retEnum.getStatus()) {
                ApplyOpenAccountStatus updObj = new ApplyOpenAccountStatus();
                updObj.setId(source.getId());
                updObj.setStatus(retEnum.getStatus());
                if(retEnum.getStatus() == OpenAccountApplyStatusEnum.APPLYMENT_STATE_REJECTED.getStatus()
                || retEnum.getStatus() == OpenAccountApplyStatusEnum.APPLYMENT_STATE_FREEZED.getStatus()) {
                    // 如果驳回需要回写驳回原因
                    updObj.setRejectReason(target.get("reject_reason"));
                }
                updObj.setUpdateTime(new Date());
                int rows = applyOpenAccountStatusService.updateByPrimaryKeySelective(updObj);
                if(rows < 1) {
                    log.error("QueryOpenAccountStatusService#syncStatusData update status error. updObj:{}", JSONUtils.toJSON(updObj));
                    return false;
                }
                return true;
            }
        } catch (Exception e) {
            log.error("QueryOpenAccountStatusService#syncStatusData exception, e:{}");
        }
        return false;
    }
    /**
     * 发送给业务侧
     */
    public void notification(ApplyOpenAccountStatus applyOpenAccountStatus,Map<String, String> respMap){
        try {
            PayAccount payAccount = payAccountService.getPayAccountByAccountId(applyOpenAccountStatus.getAccountId());
            ApplypayUserInfo applypayUserInfo = applypayUserInfoService.queryUserInfoByAccountId(applyOpenAccountStatus.getAccountId());
            if(null == applypayUserInfo) {
                log.error("QueryOpenAccountStatusService#notification query applypayUserInfo is exist. applyOpenAccountStatus:{}", JSONUtils.toJSON(applyOpenAccountStatus));
                return;
            }

            String applymentState = respMap.get("applyment_state");
            OpenAccountApplyStatusEnum retEnum = OpenAccountApplyStatusEnum.getEnum(applymentState);

            // 如果处于审核中、编辑中、审核驳回 无需通知
            if(retEnum.getStatus() == OpenAccountApplyStatusEnum.APPLYMENT_STATE_WAITTING_FOR_AUDIT.getStatus()
                    || retEnum.getStatus() == OpenAccountApplyStatusEnum.APPLYMENT_STATE_EDITTING.getStatus()
                    || retEnum.getStatus() == OpenAccountApplyStatusEnum.APPLYMENT_STATE_REJECTED.getStatus()) {
                return;
            }

            // 其余状态需要发送小程序码图片给业务侧
            Map<String, Object> map = new HashMap<>();
            map.put("url","data:image/png;base64,"+respMap.get("qrcode_data"));
            map.put("operationTips", retEnum.getTips());
            String type = "";
            switch (retEnum) {
                case APPLYMENT_STATE_WAITTING_FOR_CONFIRM_CONTACT:
                    type = CallbackResultVo.APPLYMENT_STATE_WAITTING_FOR_CONFIRM_CONTACT;
                    break;
                case APPLYMENT_STATE_WAITTING_FOR_CONFIRM_LEGALPERSON:
                    type = CallbackResultVo.APPLYMENT_STATE_WAITTING_FOR_CONFIRM_LEGALPERSON;
                    break;
                case APPLYMENT_STATE_PASSED:
                    type = CallbackResultVo.APPLYMENT_STATE_PASSED;
                    break;
                case APPLYMENT_STATE_FREEZED:
                    type = CallbackResultVo.APPLYMENT_STATE_FREEZED;
                    break;
            }
            callbackRunner.callback(payAccount.getBusinessUserId(), type,0,0,null,applypayUserInfo.getCallback(),"",null,JSONUtils.toJSON(map));
        } catch (Exception e) {
            log.error("QueryOpenAccountStatusService#notification exception, e:{}", e);
        }
    }

    /**
     * 查询报件状态
     * 1.查询本地报件中状态数据
     * 2.查询三方状态
     * 3.更新报件状态
     * 4..触发开通支付功能
     */
    @Override
    public void queryCreatePayStatus() {
        log.info("【xyy.elastic.job.QueryCreatePayStatusJob】QueryCreatePayStatusService#queryCreatePayStatus begin");
        Long beginTime = System.currentTimeMillis();
        Integer cnt = 0;
        Integer offset = 0;

        while (true) {
            List<ApplypayUserInfo> applypayUserInfos = applypayUserInfoService.queryUserInfoByStatus(OpenPayStatusEnum.OPENING.getStatus(),
                    offset, BaseConstants.DEFAULT_PAGE_SIZE);

            if(CollectionUtils.isEmpty(applypayUserInfos)) {
                break;
            }

            cnt += applypayUserInfos.size();
            offset += BaseConstants.DEFAULT_PAGE_SIZE;

            for(ApplypayUserInfo applypayUserInfo : applypayUserInfos) {
                try {
                    PayAccount payAccount = payAccountService.getPayAccountByAccountId(applypayUserInfo.getAccountId());
                    if(null == payAccount) {
                        throw new PaymentException(ResultCodeEnum.USER_NOT_FOUND);
                    }
                    QueryCreateAllPayBo result = routeManager.queryCreateAllPay(ChannelConstants.CHANNEL_FUMIN_BANK_NAME,applypayUserInfo.getAccountId(),
                            payAccount.getBusinessIdType());

                    // WAIT_AUDIT 审核中 RE_WAIT_AUDIT 再次提交信息审核中
                    if("WAIT_AUDIT".equals(result.getStatus()) ||
                            "RE_WAIT_AUDIT".equals(result.getStatus()))
                    {
                        continue;
                    }

                    // EXCEPTION 进件异常 REGISTER_FAIL 进件失败 AUDIT_FAIL审核失败
                    if("EXCEPTION".equals(result.getStatus()) ||
                            "REGISTER_FAIL".equals(result.getStatus()) || "AUDIT_FAIL".equals(result.getStatus()))
                    {
                        // 判断是否更新过状态
                        if(!OpenPayStatusEnum.FAIL.getStatus().equals(applypayUserInfo.getStatus())) {
                            ApplypayUserInfo updObj = new ApplypayUserInfo();
                            updObj.setId(applypayUserInfo.getId());
                            updObj.setStatus(OpenPayStatusEnum.FAIL.getStatus());
                            updObj.setMessage(result.getMessage());
                            int rows = applypayUserInfoService.updateByPrimaryKeySelective(updObj);
                            if(rows < 1) {
                                throw new PaymentException(ResultCodeEnum.DATABASE_ERROR);
                            }

                            // 通知业务方
                            log.warn("QueryCreatePayStatusService#queryCreatePayStatus openAccountApplyment fail. result:{}", JSONUtils.toJSON(result));
                            callbackRunner.callback(payAccount.getBusinessUserId(), CallbackResultVo.TYPE_OPEN_ACCOUNT_FAIL, 0,0,null,applypayUserInfo.getCallback(), "", result.getMessage());
                        }
                        continue;
                    }

                    // SUCCESS 审核成功
                    if("SUCCESS".equals(result.getStatus())) {
                        try {
                            openAccountService.openPay(payAccount.getAccountId(), Arrays.asList(FBankPowerIdEnum.values()));
                        } catch (PaymentException e) {
                            log.error("QueryCreatePayStatusService#queryCreatePayStatus openAccountService.openPay fail. applypayUserInfo:{}", JSONUtils.toJSON(applypayUserInfo), e);
                            throw e;
                        }

                        // 获取特约商户号
                        List<OpenPayBo> openPayList = result.getOpenPayList();
                        String subMchid = "";
                        try {
                            if(CollectionUtils.isNotEmpty(openPayList)) {
                                subMchid = openPayList.stream().filter(item->{
                                    // 过滤 只需要微信的商户号
                                    if(FBankPowerIdEnum.WX_OFFICIAL.getPowerId().equals(item.getPowerId())
                                            || FBankPowerIdEnum.WX_MINI.getPowerId().equals(item.getPowerId())
                                            || FBankPowerIdEnum.WX_APP.getPowerId().equals(item.getPowerId())
                                            || FBankPowerIdEnum.WX_BAR_CODE.getPowerId().equals(item.getPowerId())
                                            || FBankPowerIdEnum.WX_SCAN_CODE.getPowerId().equals(item.getPowerId())){
                                        return true;
                                    }
                                    return false;
                                }).map(OpenPayBo::getSubMchid).distinct().findFirst().get();
                            }
                        } catch (Exception e) {
                            log.error("QueryCreatePayStatusService#queryCreatePayStatus get subMchid fail. openPayList:{}", JSONUtils.toJSON(openPayList), e);
                        }
                        ApplypayUserInfo updObj = new ApplypayUserInfo();
                        updObj.setId(applypayUserInfo.getId());
                        updObj.setStatus(OpenPayStatusEnum.SUCCESS_FM.getStatus());
                        updObj.setMessage(OpenPayStatusEnum.SUCCESS_FM.getDesc());
                        if(StringUtils.isNotBlank(subMchid)) {
                            updObj.setSubMchid(subMchid);
                        }
                        int rows = applypayUserInfoService.updateByPrimaryKeySelective(updObj);
                        if(rows < 1) {
                            throw new PaymentException(ResultCodeEnum.DATABASE_ERROR);
                        }

                        log.info("AccountChangeController#openPayChannel accountId:{}", applypayUserInfo.getAccountId());
                        // 开户意愿申请单
                        ThirdUserInfo thirdUserInfo = thirdUserInfoService.getThirdUserInfoByUserId(applypayUserInfo.getAccountId());
                        ResultVO resultVO = openAccountService.openAccountApplyment(applypayUserInfo.getAccountId(), thirdUserInfo.getThirdUserId());
                        if (resultVO.isSuccess()) {
                            // 提交申请成功
                            log.info("AccountChangeController#openPayChannel openAccountApplyment succeed.");
                        } else {
                            log.error("AccountChangeController#openPayChannel openAccountApplyment fail. thirdUserInfo:{}, result:{}", JSONUtils.toJSON(thirdUserInfo), JSONUtils.toJSON(resultVO));
                        }
                    }
                }
                catch(Exception ex) {
                    log.error(ex.getMessage(), ex);
                }
            }
        }

        log.info("QueryOpenAccountJobServiceImpl#queryCreatePayStatus end," +
                "deal applypayUserInfos size：{}, cost：{}", cnt, System.currentTimeMillis() - beginTime);
    }

    @Override
    public void queryOpenPayStatus() {
        log.info("QueryOpenAccountJobServiceImpl#queryOpenPayStatus begin");
        queryOpenPayStatus(OpenPayStatusEnum.OPENING.getStatus());
        queryOpenPayStatus(OpenPayStatusEnum.FAIL.getStatus());
    }

    private void queryOpenPayStatus(Integer status){
        Long beginTime = System.currentTimeMillis();
        Integer cnt = 0;
        Integer offset = 0;

        while(true) {
            List<OpenpayInfo> openpayInfos = openpayInfoService.queryByStatus(status,
                    offset, BaseConstants.DEFAULT_PAGE_SIZE);

            if(CollectionUtils.isEmpty(openpayInfos)) {
                break;
            }

            cnt += openpayInfos.size();
            offset += Constants.DEFAULT_PAGE_SIZE;

            for(OpenpayInfo openpayInfo : openpayInfos) {
                try {
                    PayAccount payAccount = payAccountService.getPayAccountByAccountId(openpayInfo.getAccountId());
                    if(null == payAccount) {
                        throw new PaymentException(ResultCodeEnum.USER_NOT_FOUND);
                    }
                    Map<String, Boolean> result = routeManager.queryOpenPay(ChannelConstants.CHANNEL_FUMIN_BANK_NAME, openpayInfo.getAccountId(),
                            payAccount.getBusinessIdType());

                    for(String powerId : result.keySet()) {
                        OpenpayInfo record = new OpenpayInfo();
                        record.setStatus(result.get(powerId) ? OpenPayStatusEnum.SUCCESS_FM.getStatus() : OpenPayStatusEnum.FAIL.getStatus());
                        record.setAccountId(openpayInfo.getAccountId());
                        record.setThirdUserInfoId(openpayInfo.getThirdUserInfoId());
                        record.setPowerId(powerId);
                        record.setVersion(openpayInfo.getStatus());
                        int rows = openpayInfoService.updateStatusWhereOpening(record);
                        if(rows < 1) {
                            log.error("QueryOpenAccountJobServiceImpl#queryOpenPayStatus database error. OpenpayInfo:{}", JSONUtils.toJSON(record));
//                            throw new PaymentException(ResultCodeEnum.DATABASE_ERROR);
                        }
                    }
                }
                catch(Exception ex) {
                    log.error(ex.getMessage(), ex);
                }
            }
        }

        log.info("QueryOpenAccountJobServiceImpl#queryOpenPayStatus end," +
                "deal applypayUserInfos size：{}, cost：{}", cnt, System.currentTimeMillis() - beginTime);
    }


}